package com.atguigu.auth.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.atguigu.auth.common.SmsCommon;
import com.atguigu.auth.feign.MemberFeign;
import com.atguigu.auth.feign.ThirdFeign;
import com.atguigu.auth.unit.HttpUtils;
import com.atguigu.common.to.UmsMemberEntity;
import com.atguigu.common.to.AutoLoginResponse;
import com.atguigu.auth.vo.GiteeUserInfoVo;
import com.atguigu.auth.vo.UserLoginVo;
import com.atguigu.auth.vo.UserRegistVo;
import com.atguigu.common.exception.enumtion.ExceptionEnum;
import com.atguigu.common.utils.R;
import lombok.Data;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


/**
 * 商品html渲染信息
 *
 * @author qhw
 * @email qhw@gmail.com
 * @date 2021-08-03 19:57:10
 */
@Controller
@Data
@ConfigurationProperties("auto.login")
public class AutoController {


    private String clientId;//社交登录获取token的client_id

    private String clientSecret; //社交登录获取token的client_secret

    private String redirectUri; //回调的地址

    private String grantType; //类型


    @Autowired
    private ThirdFeign thirdFeign;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MemberFeign memberFeign;

    @GetMapping("login.html")
    public String login(HttpSession session) {
        //判断是否带着token有的话直接登录即可
        Object attribute = session.getAttribute(AutoLoginResponse.REDIS_SESSION_LOGIN);
        if (attribute == null) {
            return "login";
        } else {
            return "redirect:http://gulimail.com";
        }


    }


    @GetMapping("ret.html")
    public String ret() {
        return "ret";

    }


    @GetMapping("/sms/sendcode")
    @ResponseBody
    public R sendCode(@RequestParam("phone") String phone) {
        //根据key来获取验证码
        String s = stringRedisTemplate.opsForValue().get(SmsCommon.SMS_CODE_KEY + phone);
        if (s != null) {
            //说明存过该手机的验证码了-并且没有过期
            Long time = Long.parseLong(s.split("_")[1]);
            if (System.currentTimeMillis() - time < 60000) {
                //说明不到60s重复发送验证码
                return R.error(ExceptionEnum.SMS_CODE_REPEAT.getCode(), ExceptionEnum.SMS_CODE_REPEAT.getMsg());
            }

        }

        //生成6为验证码--存当前时间的目的在于需要判断是否过于频繁请求--60s不可以过多请求
        //虽然我们在前端控制1分钟不可以过多请求，但是防止恶意刷验证码，后台需要去做判断
        String code = UUID.randomUUID().toString().substring(0, 5);
        //远程发送短信获取验证码
        thirdFeign.sendCode(code, phone);
        //将验证码放入redis中--默认5分钟后失效
        stringRedisTemplate.opsForValue().set(SmsCommon.SMS_CODE_KEY + phone, code + "_" + System.currentTimeMillis(), 5, TimeUnit.MINUTES);

        return R.ok();

    }


    /**
     * 注册请求接口
     *
     * @return
     */
    @PostMapping("/regist")
    public String ret(@Valid UserRegistVo userRegistVo, BindingResult result, RedirectAttributes redirectAttributes) {

        //做检验
        if (result.hasErrors()) {
            //说明校验不通过--收集错误信息
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimail.com/ret.html";
        }

        //走到这一步说明基本属性没有出现问题

        //检验验证码
        String code = stringRedisTemplate.opsForValue().get(SmsCommon.SMS_CODE_KEY + userRegistVo.getPhone());
        if (code != null) {
            if (code.split("_")[0].equals(userRegistVo.getCode())) {
                //删除令牌--执行业务
                stringRedisTemplate.delete(SmsCommon.SMS_CODE_KEY + userRegistVo.getPhone());
                //远程调用接口完成注册
                memberFeign.ret(userRegistVo);
                return "redirect:http://auth.gulimail.com/login.html";
            } else {
                Map<String, String> errors = new HashMap<>();
                errors.put("code", "验证码错误");
                redirectAttributes.addFlashAttribute("errors", errors);
                return "redirect:http://auth.gulimail.com/ret.html";
            }

        } else {
            Map<String, String> errors = new HashMap<>();
            errors.put("code", "验证码过期，请重新请求");
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimail.com/ret.html";
        }


    }


    @PostMapping("/login")
    public String sendCode(UserLoginVo userLoginVo, RedirectAttributes redirectAttributes,HttpSession session) {
        //远程调用接口完成登录
        R login = memberFeign.login(userLoginVo);
        if (login.getCode() == 0) {
            UmsMemberEntity umsMemberEntity = login.getData("data", new TypeReference<UmsMemberEntity>() {
            });
            //登录成功跳转首页
            session.setAttribute(AutoLoginResponse.REDIS_SESSION_LOGIN,umsMemberEntity);
            return "redirect:http://gulimail.com";
        } else {
            Map<String, String> errors = new HashMap<>();
            String msg = login.getData("msg", new TypeReference<String>() {
            });
            errors.put("msg", msg);
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.gulimail.com/login.html";
        }


    }

    /**
     * 社交登录回调接口
     *
     * @param
     * @param
     * @return
     */
    @GetMapping("/auto/login/success")
    public String autoLoginSuccess(@RequestParam("code") String code, HttpSession session) throws Exception {
        Map<String, String> headers = new HashMap<>();
        Map<String, String> querys = new HashMap<>();
        //根据登录成功的code码来获取access-token
        Map<String, String> map = new HashMap<>();
        map.put("grant_type", getGrantType());
        map.put("code", code);
        map.put("client_id", getClientId());
        map.put("client_secret", getClientSecret());
        map.put("redirect_uri", getRedirectUri());
        HttpResponse response = HttpUtils.doPost("https://gitee.com", "/oauth/token", "POST", headers, querys, map);
        if (response.getStatusLine().getStatusCode() == 200) {
            //请求成功--正确处理业务--获取uuid--以及登录信息远程调用member完成注册登录
            String enerty = EntityUtils.toString(response.getEntity());
            AutoLoginResponse loginResponse = JSON.parseObject(enerty, AutoLoginResponse.class);
            //查询社交用户的id--用来作为社交登录的唯一id
            HttpResponse response1 = HttpUtils.doGet("https://gitee.com", "/api/v5/user?access_token=" + loginResponse.getAccessToken(), "GET", headers, querys);
            if (response1.getStatusLine().getStatusCode() == 200) {
                //获取登录id以及用户名称
                String string = EntityUtils.toString(response1.getEntity());
                GiteeUserInfoVo giteeUserInfoVo = JSON.parseObject(string, GiteeUserInfoVo.class);
                loginResponse.setUid(giteeUserInfoVo.getId());
                loginResponse.setUserName(giteeUserInfoVo.getName());

                //远程调用会员服务完成登录注册
                R r = memberFeign.autoLogin(loginResponse);
                if (r.getCode() == 0) {
                    //将用户信息放入session中
                    session.setAttribute(AutoLoginResponse.REDIS_SESSION_LOGIN, loginResponse);
                    return "redirect:http://gulimail.com";
                }
            }
        }
        return null;

    }


}
